﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpModifyJoinRelationship.h"
#include "IDocument.h"
#include "IInstance.h"
#include "ElementId.h"
#include "CutUtils.h"
#include "JoinUtils.h"
#include "IElementShapeHandle.h"
#include "NotificationUtils.h"
#include "IJoinRelationshipBehavior.h"

#include "GbmpWallUtils.h"
#include "GbmpBeamUtils.h"
#include "GbmpStripFoundationUtils.h"
#include "GbmpJoinUtils.h"
#include "GbmpCutUtils.h"
#include "GbmpJoinConditionUtils.h"
#include "IGeometryRelationshipComponent.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
using namespace gcmp;

void GbmpModifyJoinRelationship::BuildJoinInMoveElements(gcmp::IDocument*pDoc, const gcmp::ElementId& moveElementId) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDoc指针无效",L"GDMPLab",L"2024-03-30");
    //墙柱连接
    IInstance* pAttachingInstance = quick_cast<IInstance>(pDoc->GetElement(moveElementId));
    if (pAttachingInstance != nullptr)
    {
        CutUtils::DeleteElementCutsIfNotAllowCutByCutterOrCutteeId(pDoc, pAttachingInstance->GetElementId());
        GbmpCutUtils::CreateWallColumnCutRelationship(pDoc, pAttachingInstance);
        GbmpJoinUtils::CreateJoinsAndCuts(pDoc, pAttachingInstance);
    }
}

void GbmpModifyJoinRelationship::BuildJoinInMoveGripPoints(gcmp::IDocument*pDoc, const gcmp::ElementId& moveElementId) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDoc指针无效",L"GDMPLab",L"2024-03-30");

    IElementShapeHandle* pGrip = quick_cast<IElementShapeHandle>(pDoc->GetElement(moveElementId));
    if (!pGrip)
        return;
    IInstance* pAttachingObject = quick_cast<IInstance>(pDoc->GetElement(pGrip->GetMasterId()));
    if (pAttachingObject != nullptr)
    {
        NotificationNotSatisfyGeometryJoin(pDoc, pAttachingObject);
        CutUtils::DeleteElementCutsIfNotAllowCutByCutterOrCutteeId(pDoc, pAttachingObject->GetElementId());
        if (GbmpWallUtils::IsWall(pAttachingObject))
        {
            GbmpCutUtils::CreateWallColumnCutRelationship(pDoc, pAttachingObject);

            if (!GbmpWallUtils::IsJoinable(pAttachingObject))
                return;

            GbmpJoinUtils::CreateWallWallJoins(pDoc, pAttachingObject);
        }
        else if (GbmpBeamUtils::IsBeam(pAttachingObject))
        {
            GbmpJoinUtils::CreateBeamBeamJoins(pDoc, pAttachingObject);
        }
        else if (GbmpStripFoundationUtils::IsStripFoundation(pAttachingObject))
        {
            GbmpJoinUtils::CreateStripFoundationJoins(pDoc, pAttachingObject);
        }
    }
}

void GbmpModifyJoinRelationship::DeleteMoveElementJoins(gcmp::IDocument*pDoc, const gcmp::ElementId& moveElementId) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDoc指针无效",L"GDMPLab",L"2024-03-30");
    IElementShapeHandle* pGrip = quick_cast<IElementShapeHandle>(pDoc->GetElement(moveElementId));
    if (pGrip != nullptr)
    {
        IElement* pAttachingElement = pDoc->GetElement(pGrip->GetMasterId());
        JoinPosition attachingJoinEnd = (JoinPosition)pGrip->GetPositionIndexInMasterElement();
        if (attachingJoinEnd == JoinPosition::Start)
        {
            ElementJoinUtils::DeleteJoinsByJoinPosition(pAttachingElement, JoinPosition::Start);
            ElementJoinUtils::DeleteJoinsByJoinPosition(pAttachingElement, JoinPosition::Middle);
        }
        else if (attachingJoinEnd == JoinPosition::End)
        {
            ElementJoinUtils::DeleteJoinsByJoinPosition(pAttachingElement, JoinPosition::End);
            ElementJoinUtils::DeleteJoinsByJoinPosition(pAttachingElement, JoinPosition::Middle);
        }
        else if (attachingJoinEnd == JoinPosition::Middle)
        {
            ElementJoinUtils::DeleteJoinsByJoinPosition(pAttachingElement, JoinPosition::Middle);
        }
        else
        {
            ElementJoinUtils::DeleteAllElementJoins(pDoc, pGrip->GetMasterId());
        }
    }
    else
    {
        ElementJoinUtils::DeleteAllElementJoins(pDoc, moveElementId);
    }
}

void GbmpModifyJoinRelationship::NotificationNotSatisfyGeometryJoin(gcmp::IDocument* pDoc, gcmp::IInstance* pInstance) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"无效pDoc",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pInstance, L"无效pInstance",L"GDMPLab",L"2024-03-30");

    const IGeometryRelationshipComponent* pGeometryRepCpt = pInstance->GetGeometryRelationshipComponent();
    if (pGeometryRepCpt) {
        const IJoinRelationshipBehavior* pJoinRelationshipBehavior = pGeometryRepCpt->GetJoinRelationship();
        if (!pJoinRelationshipBehavior)
            return;
        const std::vector<ElementId>& startJoins = pJoinRelationshipBehavior->GetElementJoinIdsAtStart();
        DBG_WARN_AND_RETURN_VOID_UNLESS(startJoins.size() <= 1, L"默认的连接不支持端点处多个连接",L"GDMPLab",L"2024-03-30");
        if (startJoins.size() == 1)
        {
            IElementJoin *pStartJoin = quick_cast<IElementJoin>(pDoc->GetElement(startJoins.at(0)));
            if (pStartJoin != nullptr)
            {
                NotificationNotSatisfyGeometryJoin(pDoc, pStartJoin);
            }
        }

        const std::vector<ElementId>& endJoins = pJoinRelationshipBehavior->GetElementJoinIdsAtEnd();
        DBG_WARN_AND_RETURN_VOID_UNLESS(endJoins.size() <= 1, L"默认的连接不支持端点处多个连接",L"GDMPLab",L"2024-03-30");
        if (endJoins.size() == 1)
        {
            IElementJoin *pEndJoin = quick_cast<IElementJoin>(pDoc->GetElement(endJoins.at(0)));
            if (pEndJoin != nullptr)
            {
                NotificationNotSatisfyGeometryJoin(pDoc, pEndJoin);
            }
        }
    }
}

void GbmpModifyJoinRelationship::NotificationNotSatisfyGeometryJoin(gcmp::IDocument* pDoc, IElementJoin *pJoin) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"无效pDoc",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pJoin, L"无效pJoin",L"GDMPLab",L"2024-03-30");
    IElementJoinBehavior* pElementJoinBehavior = pJoin->GetElementJoinBehavior();
    if (!pElementJoinBehavior)
        return;
    //不满足几何连接时，弹出弱提示 
    if (!GbmpJoinConditionUtils::IsSatisfyGeometryJoin(pDoc, pJoin))
    {
        const INotification* lastNotification = NotificationUtils::GetLastNotification();
        NotificationTypes notiType = NotificationTypes::WarningNotificationType;
        std::wstring notiText = GBMP_TR(L"构件过短或角度过小，连接失败！");
        NotificationUtils::PostNotification(notiType, notiText);
    }
}
